#pragma once

#include "MultigridSolver.h"

/**
 * @file Projection.h
 * @author xingyifan
 * @date 2022-08-31 17:07
 *
 * @description: 投影算子 P = I-GL^-1D
 */

template <int Dim>
class Projection
{
public:
    GridX<Dim> operator()(GridX<Dim> &U)
    {
        // 散度算子，梯度算子
        Divergence<Dim> divergence;
        Gradient<Dim> gradient;

        // 创建填充器
        GhostFiller<Dim> ghostfiller;

        // 第一步填充 Du = D*U
        Grid<Dim> Du = divergence(U, ghostfiller);

        // 系统规模
        int n = Du.width();

        // 初始化容器
        Grid<Dim> V(n, 0);

        // 多重网格求解器
        MultigridSolver<Dim> msolver;

        // 求解 Poisson 方程 LV = Du
        msolver.solve(Du, V);

        // 梯度算子作用 W = G*V
        GridX<Dim> W = gradient(V, ghostfiller);

        // 作差 I-W
        for (int d = 0; d < Dim; d++)
        {
            W[d] = std::move(U[d] - W[d]);
        }

        return W;
    }
};
